frontend/pages/e/[uuid]/details.tsx (view raw)
1import moment from 'moment';
2import Button from '@mui/material/Button';
3import Box from '@mui/material/Box';
4import Link from '@mui/material/Link';
5import Paper from '@mui/material/Paper';
6import Divider from '@mui/material/Divider';
7import Container from '@mui/material/Container';
8import TextField from '@mui/material/TextField';
9import Typography from '@mui/material/Typography';
10import {useTheme} from '@mui/material/styles';
11import {DatePicker} from '@mui/x-date-pickers/DatePicker';
12import {PropsWithChildren, useState} from 'react';
13import {useTranslation} from 'react-i18next';
14import pageUtils from '../../../lib/pageUtils';
15import ShareEvent from '../../../containers/ShareEvent';
16import useEventStore from '../../../stores/useEventStore';
17import useToastStore from '../../../stores/useToastStore';
18import useSettings from '../../../hooks/useSettings';
19import EventLayout, {TabComponent} from '../../../layouts/Event';
20import {
21 EventByUuidDocument,
22 useUpdateEventMutation,
23} from '../../../generated/graphql';
24import SupportCaroster from '../../../containers/SupportCaroster';
25
26interface Props {
27 eventUUID: string;
28 announcement?: string;
29}
30
31const Page = (props: PropsWithChildren<Props>) => {
32 return <EventLayout {...props} Tab={DetailsTab} />;
33};
34
35const DetailsTab: TabComponent = ({}) => {
36 const {t} = useTranslation();
37 const theme = useTheme();
38 const settings = useSettings();
39 const [updateEvent] = useUpdateEventMutation();
40 const addToast = useToastStore(s => s.addToast);
41 const setEventUpdate = useEventStore(s => s.setEventUpdate);
42 const event = useEventStore(s => s.event);
43 const [isEditing, setIsEditing] = useState(false);
44 const idPrefix = isEditing ? 'EditEvent' : 'Event';
45
46 const onSave = async e => {
47 try {
48 const {uuid, ...data} = event;
49 const {id, travels, waitingPassengers, __typename, ...input} = data;
50 await updateEvent({
51 variables: {uuid, eventUpdate: input},
52 refetchQueries: ['eventByUUID'],
53 });
54 setIsEditing(false);
55 } catch (error) {
56 console.error(error);
57 addToast(t('event.errors.cant_update'));
58 }
59 };
60 const sectionSx = {
61 marginBottom: theme.spacing(2),
62 width: '540px',
63 maxWidth: '100%',
64 paddingX: theme.spacing(2),
65 };
66
67 const modifyButton = isEditing ? (
68 <Button
69 variant="contained"
70 color="primary"
71 sx={{position: 'absolute', right: theme.spacing(2)}}
72 onClick={onSave}
73 >
74 {t('event.details.save')}
75 </Button>
76 ) : (
77 <Button
78 variant="text"
79 color="primary"
80 sx={{position: 'absolute', right: theme.spacing(2)}}
81 onClick={() => setIsEditing(true)}
82 >
83 {t('event.details.modify')}
84 </Button>
85 );
86
87 if (!event) return null;
88
89 return (
90 <Box
91 sx={{
92 position: 'relative',
93 paddingLeft: '80px',
94
95 [theme.breakpoints.down('md')]: {
96 paddingLeft: 0,
97 paddingBottom: '80px',
98 },
99 }}
100 >
101 <Container maxWidth="sm" sx={{marginTop: theme.spacing(6)}}>
102 <Paper sx={{position: 'relative', padding: theme.spacing(2)}}>
103 {modifyButton}
104 <Box sx={sectionSx}>
105 <Typography variant="h6">{t('event.fields.name')}</Typography>
106 {isEditing ? (
107 <TextField
108 fullWidth
109 value={event.name}
110 onChange={e => setEventUpdate({name: e.target.value})}
111 name="name"
112 id="EditEventName"
113 />
114 ) : (
115 <Typography variant="body1" id={`${idPrefix}Name`}>
116 {event.name ?? t('event.fields.empty')}
117 </Typography>
118 )}
119 </Box>
120 <Box sx={sectionSx}>
121 <Typography variant="h6">{t('event.fields.date')}</Typography>
122 {isEditing ? (
123 <DatePicker
124 renderInput={props => (
125 <TextField
126 {...props}
127 id={`${idPrefix}Date`}
128 fullWidth
129 placeholder={t('event.fields.date_placeholder')}
130 />
131 )}
132 inputFormat="DD/MM/yyyy"
133 value={event.date}
134 onChange={date =>
135 setEventUpdate({
136 date: !date ? null : moment(date).format('YYYY-MM-DD'),
137 })
138 }
139 />
140 ) : (
141 <Typography variant="body1" id={`${idPrefix}Date`}>
142 {event.date
143 ? moment(event.date).format('DD/MM/YYYY')
144 : t('event.fields.empty')}
145 </Typography>
146 )}
147 </Box>
148 <Box sx={sectionSx}>
149 <Typography variant="h6">{t('event.fields.address')}</Typography>
150 {isEditing ? (
151 <TextField
152 fullWidth
153 multiline
154 maxRows={4}
155 inputProps={{maxLength: 250}}
156 helperText={`${event.address?.length ?? 0}/250`}
157 defaultValue={event.address}
158 value={event.address}
159 onChange={e => setEventUpdate({address: e.target.value})}
160 id={`${idPrefix}Address`}
161 name="address"
162 />
163 ) : (
164 <Typography variant="body1" id={`${idPrefix}Address`}>
165 {event.address ? (
166 <Link
167 target="_blank"
168 rel="noreferrer"
169 href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
170 event.address
171 )}`}
172 onClick={e => e.preventDefault}
173 >
174 {event.address}
175 </Link>
176 ) : (
177 t('event.fields.empty')
178 )}
179 </Typography>
180 )}
181 </Box>
182 <Box sx={sectionSx}>
183 <Typography variant="h6">
184 {t('event.fields.description')}
185 </Typography>
186 {isEditing ? (
187 <TextField
188 fullWidth
189 multiline
190 maxRows={4}
191 inputProps={{maxLength: 250}}
192 helperText={`${event.description?.length || 0}/250`}
193 defaultValue={event.description}
194 value={event.description || ''}
195 onChange={e => setEventUpdate({description: e.target.value})}
196 id={`${idPrefix}Description`}
197 name="description"
198 />
199 ) : (
200 <Typography variant="body1" id={`${idPrefix}Description`}>
201 {event.description ?? t('event.fields.empty')}
202 </Typography>
203 )}
204 </Box>
205 <Box sx={sectionSx}>
206 <Typography variant="h6">{t('event.fields.link')}</Typography>
207 <Typography>{t('event.fields.link_desc')}</Typography>
208 </Box>
209 <Box pt={4} pb={2} justifyContent="center" display="flex">
210 <ShareEvent title={`Caroster ${event.name}`} />{' '}
211 </Box>
212 </Paper>
213 <Box mt={4} display="flex" justifyContent="center">
214 <SupportCaroster />
215 </Box>
216 </Container>
217 </Box>
218 );
219};
220
221export const getServerSideProps = pageUtils.getServerSideProps(
222 async (context, apolloClient) => {
223 const {uuid} = context.query;
224 const {host = ''} = context.req.headers;
225 let event = null;
226
227 // Fetch event
228 try {
229 const {data} = await apolloClient.query({
230 query: EventByUuidDocument,
231 variables: {uuid},
232 });
233 event = data?.eventByUUID?.data;
234 } catch (error) {
235 return {
236 notFound: true,
237 };
238 }
239
240 return {
241 props: {
242 eventUUID: uuid,
243 metas: {
244 title: event?.attributes?.name || '',
245 url: `https://${host}${context.resolvedUrl}`,
246 },
247 },
248 };
249 }
250);
251export default Page;